/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "引擎.h"


#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/vulkan-1.lib")
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/VkLayer_utils.lib")
 

#include <node后端.h>
#include "物体编辑/物体编辑.h"



S_Engine		S_框架::engine;
S_设备环境		S_框架::ctx;
S_设备			S_框架::GPU;

uint32          S_框架::版本号[2] = {0,0};



S_Scene*		S_框架::g_Scene			= nullptr;
S_线管*			S_框架::g_索引绘制线管	= nullptr;
S_线管*			S_框架::g_线段绘制线管	= nullptr;
S_着色*			S_框架::g_单色Shader	= nullptr;
S_材质*			S_框架::g_线段绘制材质	= nullptr;
S_材质*			S_框架::g_索引绘制材质	= nullptr;


S_材质*			S_框架::g_体素BOX材质	= nullptr;
S_材质*			S_框架::g_VecSphere材质 = nullptr;
S_材质*			S_框架::g_Cube材质		= nullptr;


//S_摄像机*            S_框架::g_当前操作摄像机  = nullptr;
//S_物体*			S_框架::g_变换手柄_准备替换 = nullptr;
S_物体*              S_框架::g_基准网格线 = nullptr;

S_物体*			     S_框架::g_变换手柄        = nullptr;
std::vector<S_物体*> S_框架::g_变换手柄方向线;
std::vector<S_物体*> S_框架::g_变换手柄圆圈线;
std::vector<S_物体*> S_框架::g_变换手柄轴向线;
std::vector<S_物体*> S_框架::g_变换手柄移动箭头;
std::vector<S_物体*> S_框架::g_变换手柄缩放端点;

S_MeshTranformProp          S_框架::G变换手柄外接圆绘制属性;
S_MeshTranformProp          S_框架::G变换手柄方向线绘制属性;
S_MeshTranformProp          S_框架::G变换手柄端箭头绘制属性[3];

S_材质*              S_框架::g_手柄线材质 = nullptr;
S_材质*              S_框架::g_手柄面材质 = nullptr;

//S_物体*			S_Core::g_缩放变换手柄		= nullptr;
//S_摄像机*		S_Core::g_相机				= nullptr;
std::set<S_摄像机*>		S_框架::g_视口相机;

S_物体*			S_框架::g_当前独立显示物体	= nullptr;
S_物体*			S_框架::g_Debug物体			= nullptr;
E_物体数据类型		S_框架::g_当前独显物体类型	= E_物体数据类型::e_模型;
//S_物体* S_Core::g_场景模型 = 0;
uint32			S_框架::g_拾取手柄 = 0;


bool		S_框架::g_开启变换 = false;
E_变换		S_框架::g_变换方式	= E_变换::e_移动;
E_轴向		S_框架::g_变换轴	= E_轴向::e_XYZ;
vec3		S_框架::g_视线向量		= {};
vec2		S_框架::g_鼠标起始坐标	= {};


bool		S_框架::g_开启节点移动 = true;


//S_UI创建环境*	S_框架::g_UI环境		= 0;
S_设备环境*		S_框架::g_3D视口环境	= 0;

fp_无参数函数指针 S_框架::gfu_更新选择节点 = nullptr;



vec2		S_框架::g节点创建初始位置 = {};
bool        S_框架::g_播放帧 = false;
bool		S_框架::g_变换开关 = false;
//int32       S_框架::g_渲染帧 = 0;


S_Props		S_框架::g_变换类型开关 = {};
S_Props		S_框架::g_骨骼姿态编辑模式 = {};

E_物体类型		S_框架::g当前编辑对象类型 = E_物体类型::t_空;

//S_Props						S_Core::g_节点树容器 = f_alloc_StrIndexProp(L"");
//std::vector<S_MapPtrItem>	S_框架::g_物体节点树;
std::vector<S_MapPtrItem>	S_框架::g_材质节点树;


//static C_Widget*	g_激活节点 = nullptr;
//static C_节点基类* g_激活节点后端 = nullptr;
static std::vector<C_节点基类*>	g_激活节点;
static std::vector<S_物体拾取信息>	g_当前物体拾取;


static uint8	g_独显模型显示模式 = 2;



std::vector<S_Window*>	S_框架::g_主窗口;
C_Widget管理*			S_框架::g_UIGM = nullptr;
C_Widget*				S_框架::g_ui文件对话框 = nullptr;
S_Window*               S_框架::g_设置窗口 = nullptr;

C_Widget*				S_框架::g_ui顶层画布 = nullptr;
ui_绘制模板_画预设图形*	S_框架::m_全屏链接线背景绘制 = nullptr;
ui_绘制模板_行文本绘制*	S_框架::m_全屏链接线字符绘制;
ui_绘制模板_图标*		S_框架::m_全屏链接线图标绘制;
ui_绘制模板_自定义线*			S_框架::m_全屏链接线绘制 = new ui_绘制模板_自定义线;

S_界面框架构建*         S_框架::g_界面构建 = nullptr;


std::string    S_框架::m_库默认路径 = "I:/节点库/";





S_RGBA8UI S_主题颜色::uic_时间轴时间区 = { 50,50,50,255 };
S_RGBA8UI S_主题颜色::uic_时间网格线 = { 20,20,20,255 };
S_RGBA8UI S_主题颜色::uic_时间轴背景 = { 40,40,40,255 };
S_RGBA8UI S_主题颜色::uic_当前时间线 = { 60,200,200,255 };
S_RGBA8UI S_主题颜色::uic_节点插座文字 = { 80,80,80,255 };
S_RGBA8UI S_主题颜色::uic_节点剪刀线 = { 200,200,200,255 };
S_RGBA8UI S_主题颜色::uic_节点链接线 = { 140,140,140,255 };
S_RGBA8UI S_主题颜色::uic_节点插座 = { 100,100,100,255 };
S_RGBA8UI S_主题颜色::uic_节点面板焦点 = { 60,60,60,255 };
S_RGBA8UI S_主题颜色::uic_节点框 = { 4,4,4, 80 };
S_RGBA8UI S_主题颜色::uic_视口手柄X = { 200, 20, 20, 255 };
S_RGBA8UI S_主题颜色::uic_视口手柄Y = { 20, 200, 20, 255};
S_RGBA8UI S_主题颜色::uic_视口手柄Z = { 20, 20, 200, 255};
//S_RGBA8UI S_主题参数::uic_时间轴时间区 = {50,50,50,255};
S_RGBA8UI S_主题颜色::uic_选框面颜色 = S_RGBA8UI{ 80, 100, 180, 50 };
S_RGBA8UI S_主题颜色::uic_选框边颜色 = S_RGBA8UI{ 120, 120, 200, 200 };
S_RGBA8UI S_主题颜色::uic_物体焦点颜色 = { 250,180,0,255 };
S_RGBA8UI S_主题颜色::uic_工作区背景 = { 40, 40, 40, 255 };
//std::string S_主题颜色::uic_节点图标集 = "节点ICO";


std::string S_主题图标::ico_变换移动 = "移动变换";
std::string S_主题图标::ico_变换旋转 = "arrows64";
std::string S_主题图标::ico_变换缩放 = "export";




S_界面框架构建::S_界面框架构建() {

}





S_框架::S_框架() {

}

void S_框架::init() {
	S_框架::engine.f_InitVK();
	//S_Core::engine.f_创建绘图设备(0);

	if (1) {
		GPU = S_框架::engine.f_get光追设备();
		ctx = S_框架::engine.f_get光追设备环境(0);
	}
	else {
		GPU = S_框架::engine.f_get设备(0);
		ctx = S_框架::engine.f_get环境(0, 0);
	}
	

	g_Scene = f_scene_创建场景(0);
	g_Scene->m_绘图环境 = ctx;
	
	S_框架::engine.m_绘图框架->m_Ctx = ctx;
	//S_框架::engine.m_绘图框架->m_Ctx.m_绘图设备配置 = f_draw_创建绘图设备(ctx);
	S_框架::engine.m_当前更新场景 = g_Scene;
	//S_框架::engine.m_UIctx = new S_UI创建环境(S_框架::engine.m_绘图框架->m_Ctx, E_MS次数::e_MS_4);
	//S_框架::engine.m_UIctx->m_文字字号 = 12;

	

	
	//S_Core::g变换开关 = f_alloc_BoolProp(nullptr, L"变换开关");
	S_框架::g_变换类型开关 = f_alloc_bool_1DProp(3, L"变换");
	auto* e = f_prop_Bool_1D(S_框架::g_变换类型开关);
	e[0].m_Value = true;
	e[1].m_Value = false;
	e[2].m_Value = false;
	f_prop_Bool_1D(S_框架::g_变换类型开关)[0].m_ICO = S_主题图标::ico_变换移动;
	f_prop_Bool_1D(S_框架::g_变换类型开关)[1].m_ICO = S_主题图标::ico_变换旋转;
	f_prop_Bool_1D(S_框架::g_变换类型开关)[2].m_ICO = S_主题图标::ico_变换缩放;

	g_骨骼姿态编辑模式 = f_alloc_EnumProp(nullptr, { {L"旋转","骨头_bone"}, {L"拉扯","骨头_bone"} }, L"姿态编辑模式");
	g_骨骼姿态编辑模式.m_私有 = true;



	S_框架::m_全屏链接线背景绘制 = new ui_绘制模板_画预设图形;
	S_框架::m_全屏链接线字符绘制 = new ui_绘制模板_行文本绘制;
	S_框架::m_全屏链接线图标绘制 = new ui_绘制模板_图标;

}

void S_框架::f_初始化预设资源(S_设备环境& ctx) {
	S_节点数据::g_编译器路径 = "D:/U/DEV/_LLVM/bin/";

	//g_描边材质 = new S_单色描边材质(ctx);
	g_体素BOX材质 = new S_八叉树可视预览材质(ctx);

	S_框架::g_线段绘制材质 = new S_单色线段材质(ctx);
	S_框架::g_VecSphere材质 = new S_VecSphere可视预览材质(ctx);
	S_框架::g_Cube材质 = new S_Cube可视预览材质(ctx);


	S_框架::g_当前独立显示物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
	f_ob_set数据槽数量(S_框架::g_当前独立显示物体, 4);


	auto mesh = (S_Mesh**)S_框架::g_当前独立显示物体->m_Data;
	S_框架::g_当前独立显示物体->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN), 0);
	S_框架::g_当前独立显示物体->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN), 1);
	S_框架::g_当前独立显示物体->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN), 2);
	S_框架::g_当前独立显示物体->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN), 3);


	f_ob_set材质(S_框架::g_当前独立显示物体, f_NodeCtx_get基本光照线材质(), 0);
	f_ob_set材质(S_框架::g_当前独立显示物体, f_NodeCtx_get基本光照线材质(), 1);
	f_ob_set材质(S_框架::g_当前独立显示物体, f_NodeCtx_get基本光照面材质(), 2);
	S_框架::g_当前独立显示物体->f_关闭可视通道(3);

	f_ob_set线宽(S_框架::g_当前独立显示物体, 6.0);


	S_框架::g_Debug物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
	//S_Core::g_场景模型 = f_ob_创建物体(ctx, E_物体数据::t_空, 0);
	//S_Core::g_Scene->f_add物体(S_Core::g_当前独立显示物体);
	S_框架::g_Scene->f_add物体(S_框架::g_Debug物体);




	S_节点数据状态::g_网格编辑模式.m_UI->m_Update = f_global_set切换物体编辑着色类型;

	
}

void S_框架::close() {
	delete S_框架::m_全屏链接线绘制;

	delete S_框架::m_全屏链接线背景绘制;
	delete S_框架::m_全屏链接线字符绘制;
	delete S_框架::m_全屏链接线图标绘制;

	

	f_node_环境销毁();

	f_scene_销毁渲染器纹理(f_NodeCtx_get默认场景(), 0);
	

	
	S_框架::engine.f_释放线程数据();
	S_框架::engine.f_释放设备数据();
	S_框架::engine.f_Close();


	f_scene_销毁光追渲染器(S_框架::g_Scene);

	
	for (auto& w : S_框架::g_主窗口) {
		delete w;
	}

	

	f_prop_Release(S_框架::g_变换类型开关);

	S_UI创建环境::f_销毁绘图资源();

	
	f_scene_销毁(0);


	
}

S_Window* S_框架::f_创建窗口到列队(ivec2 size) {
	S_Window* w = f_创建窗口("mbt", S_框架::ctx, { 0,0, size.x, size.y });
	w->m_采样 = E_MS次数::e_MS_4;
	w->f_创建绘制面(S_框架::engine.m_绘图框架, S_框架::ctx, { 640, 420 });

	g_主窗口.push_back(w);
	return w;
}

void S_框架::f_销毁列队窗口() {
	for (auto& w : g_主窗口) {
		delete w;
	}
	g_主窗口.clear();
}



void f_global_所在独显模型材质(uint16 模式) {
	if (模式 != 0xff00) g_独显模型显示模式 = 模式;

	switch (模式) {
	case 0:
		S_框架::g_当前独立显示物体->f_打开可视通道(0);
		S_框架::g_当前独立显示物体->f_打开可视通道(1);
		break;

	case 1:
		S_框架::g_当前独立显示物体->f_关闭可视通道(0);
		S_框架::g_当前独立显示物体->f_打开可视通道(1);
		break;

	case 2:
		S_框架::g_当前独立显示物体->f_打开可视通道(0);
		S_框架::g_当前独立显示物体->f_关闭可视通道(1);
		break;
	}
	return;
}

//C_Widget* f_global_get激活节点() {
//	return g_激活节点;
//}

C_节点基类* f_global_get激活节点后端() {
	if(g_激活节点.size()) return g_激活节点.front();
	//return g_激活节点后端;
	return nullptr;
}

void f_global_clear激活节点() {
	for (auto node : g_激活节点) {
		auto* 虚拟体 = node->f_get虚拟体();
		if (虚拟体) {
			f_global_物体显示模式_关闭焦点(虚拟体, 虚拟体->m_实例ID);
		}
	}
	g_激活节点.clear();
	
}

void f_global_set激活节点(std::vector<C_节点基类*>& nodes) {
	//以前的物体关闭焦点绘制
	for (auto node : g_激活节点) {
		auto* 虚拟体 = node->f_get虚拟体();
		if(虚拟体) f_global_物体显示模式_关闭焦点(虚拟体, 虚拟体->m_实例ID);
	}

	std::vector<S_物体*> 可显示物体;
	g_激活节点 = nodes;
	for (auto node : g_激活节点) {
		auto* 虚拟体 = node->f_get虚拟体();
		if (虚拟体) {
			f_global_物体显示模式_打开焦点(虚拟体, 虚拟体->m_实例ID);
			可显示物体.push_back(虚拟体);
		}
	}

	return;
}

void f_global_set激活物体(std::vector<C_节点基类*>& nodes) {
	if (f_prop_Bool(S_节点数据状态::g_打开编辑模式)) return;

	for (auto& e : S_节点数据::g_选中激活物体) {
		f_global_物体显示模式_关闭焦点(e, e->m_实例ID);
	}

	S_节点数据::g_选中激活物体.clear();
	for (auto& e : nodes) {
		auto* 虚拟体 = e->f_get虚拟体();
		if (虚拟体) {
			switch (虚拟体->m_Type) {
			case E_物体类型::t_多边形:
			case E_物体类型::t_摄像机:
			case E_物体类型::t_区域光:
			case E_物体类型::t_平行光:
			case E_物体类型::t_聚光灯:
			case E_物体类型::t_网格:
			case E_物体类型::t_包:
				S_节点数据::g_选中激活物体.push_back(虚拟体);
				break;
			}
		}
	}
}

std::vector<C_节点基类*>& f_global_get激活节点() {
	return g_激活节点;
}

std::vector<C_节点基类*> f_global_get激活可视物体节点() {
	std::vector<C_节点基类*> 物体节点;
	for (auto* node : g_激活节点) {
		if (node->m_Type >= E_节点类型::e_节点Type_空物体) {
			物体节点.push_back(node);
		}
	}
	return 物体节点;
}

vec3 f_global_get激活物体中心点() {
	std::vector<S_物体*> obs;
	if (f_prop_Bool(S_节点数据状态::g_打开编辑模式)) {
		for (auto& pick : f_global_get编辑拾取物体()) {
			obs.push_back(pick.物体);
		}
	}
	else {
		for (auto& e : S_节点数据::g_选中激活物体) {
			obs.push_back(e);
		}
	}

	return f_ob_get中心(obs);
}

uint32 f_global_get选中物体数量() {
	if (f_prop_Bool(S_节点数据状态::g_打开编辑模式)) {
		return g_当前物体拾取.size();
	}
	
	uint32 num = 0;
	for (auto* node : g_激活节点) {
		if (node->m_Type >= E_节点类型::e_节点Type_空物体) {
			++num;
		}
	}
	return num;
}


static class C_节点面板* g钉住节点面板 = nullptr;
void f_global_set钉住节点(class C_节点面板* panel) {
	if (g钉住节点面板) {
		
	}

	g钉住节点面板 = panel;
}

class C_节点面板 * f_global_get钉住节点() {
	return g钉住节点面板;
}



void f_global_set拾取物体(std::vector<S_物体拾取信息>& obs, bool 清除之前物体) {
	if (清除之前物体) {
		g_当前物体拾取 = obs;
	}
	else {
		g_当前物体拾取.insert(g_当前物体拾取.end(), obs.begin(), obs.end());
	}
}

std::vector<S_物体拾取信息> f_global_get编辑拾取物体() {
	return g_当前物体拾取;
}

void f_global_clear拾取物体() {
	g_当前物体拾取.clear();
}





void f_global_变换手柄到物体中心() { 
	uint32 num = S_节点数据::g_选中激活物体.size();
	//vec3 中点 = {};
	
	if (num) {
		vec3 中点 = f_global_get激活物体中心点();
		S_框架::g_变换手柄->f_set位置(中点, 0);

		S_框架::g_变换手柄->m_渲染 = true;
	}
	else {
		S_框架::g_变换手柄->m_渲染 = false;
	}
}



static std::vector<C_节点基类*> g操作物体节点;
void f_frame_bind当前操作物体节点() {
	g操作物体节点 = f_NodeCtx_从可视物体取节点(S_节点数据::g_选中激活物体);
}

std::vector<C_节点基类*> f_frame_get操作物体节点() {
	return g操作物体节点;
}





S_主题颜色::S_主题颜色() {

}


S_主题图标::S_主题图标() {

}


static std::vector<S_剪切板*> g剪切板;

S_剪切板::S_剪切板() {
	for (auto& e : g剪切板) {
		delete e;
	}
	g剪切板.clear();
	g剪切板.push_back(this);
}

S_剪切板::~S_剪切板() {

}

S_剪切板* S_剪切板::f_get() {
	if (g剪切板.size()) {
		S_剪切板* 剪切板 = g剪切板.back();
		return 剪切板;
	}
	else {
		return nullptr;
	}
}





static void f_global_set切换物体编辑着色类型(S_Props& prop) {
	switch (S_框架::g当前编辑对象类型)
	{
	case E_物体类型::t_网格: {
		

		switch (f_prop_enum(S_节点数据状态::g_网格编辑模式))
		{
		case E_网格编辑模式::e_网格编辑_顶点: {
			break;
		}
		case E_网格编辑模式::e_网格编辑_权重: {
			for (auto& e : S_节点数据::g_选中激活物体) {
				f_ob_set材质(e, f_NodeCtx_get权重可视面材质(), 0);
				f_ob_set材质(e, f_NodeCtx_get权重可视线材质(), 1);

				//f_ob_set网格可视(e, false, 1);
				f_ob_set网格可视(e, false, 2);
			}
			break;
		}
		case E_网格编辑模式::e_网格编辑_纹理: {
			break;
		}
		default:
			for (auto& e : S_节点数据::g_选中激活物体) {
				f_ob_set材质(e, f_NodeCtx_get基本光照描边材质(), 0);
				f_ob_set材质(e, f_NodeCtx_get基本光照面材质(), 1);
				f_ob_set材质(e, f_NodeCtx_get基本光照线材质(), 2);
			}
			f_NodeCtx_物体显示模型(E_物体显示模式(f_prop_enum(S_节点数据状态::g_3D视口显示模式)));
			break;
		}
		break;
	}
	case E_物体类型::t_骨架:
	case E_物体类型::t_骨骼: {
		break;
	}
	
	case E_物体类型::t_摄像机: {
		break;
	}
	default:
		break;
	}

	
}




void f_global_set全局物体显示() {
	S_节点数据::m_独立物体set.clear();
	S_节点数据::g_选中激活物体.clear();
	f_NodeCtx_get默认场景()->m_物体set = S_节点数据::m_全局物体set;
}

void f_global_set独立物体显示(C_节点树* tree) {
	S_节点数据::m_独立物体set.clear();
	S_节点数据::g_选中激活物体.clear();

	if (tree) {
		for (auto& e : tree->m_Nodes) {
			auto* ob = e->f_get虚拟体();
			if (ob) {
				switch (ob->m_Type) {
				case E_物体类型::t_虚拟体:
					//case E_物体类型::t_实例:
					break;
				default:
					S_节点数据::m_独立物体set.insert(ob);
					break;
				}
			}
		}
	}
	
	auto* rn = tree->f_get父节点();
	if (rn) {
		auto* ob = rn->f_get虚拟体();
		if (ob) {
			switch (ob->m_Type) {
			case E_物体类型::t_虚拟体:
			//case E_物体类型::t_实例:
				break;
			default:
				S_节点数据::m_独立物体set.insert(ob);
				break;
			}
		}
	}
	S_物体* 单元素虚拟体根 = f_node_get单元素虚拟体根物体(nullptr);
	
	f_NodeCtx_get默认场景()->m_物体set = S_节点数据::m_独立物体set;
	if(单元素虚拟体根) f_NodeCtx_get默认场景()->m_物体set.insert(单元素虚拟体根);
}


